home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 4 / United Public Domain Gold 4.iso / fredfish / ff.0065.dms / ff.0065.adf / Bawk / bawkdo.c < prev    next >
C/C++ Source or Header  |  1987-04-04  |  12KB  |  768 lines

  1. /*
  2.  * Bawk C actions interpreter
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. dopattern( pat )
  8. char *pat;
  9. {
  10.     Where = PATTERN;
  11.     Actptr = pat;
  12.     getoken();
  13.     expression();
  14.     return popint();
  15. }
  16.  
  17. doaction( act )
  18. char *act;
  19. {
  20.     Where = ACTION;
  21.     Actptr = act;
  22.     getoken();
  23.     while ( Token!=T_EOF )
  24.         statement();
  25. }
  26.  
  27. expression()
  28. {
  29.     expr1();
  30.  
  31.     if ( Token==T_ASSIGN )
  32.     {
  33.         getoken();
  34.         assignment( expression() );
  35.     }
  36. }
  37.  
  38. expr1()
  39. {
  40.     int ival;
  41.  
  42.     expr2();
  43.     for ( ;; )
  44.     {
  45.         if ( Token==T_LIOR )
  46.         {
  47.             getoken();
  48.             ival = popint();
  49.             expr2();
  50.             pushint( popint() || ival );
  51.         }
  52.         else
  53.             return;
  54.     }
  55. }
  56.  
  57. expr2()
  58. {
  59.     int ival;
  60.  
  61.     expr3();
  62.     for ( ;; )
  63.     {
  64.         if ( Token==T_LAND )
  65.         {
  66.             getoken();
  67.             ival = popint();
  68.             expr3();
  69.             pushint( popint() && ival );
  70.         }
  71.         else
  72.             return;
  73.     }
  74. }
  75.  
  76. expr3()
  77. {
  78.     int ival;
  79.  
  80.     expr4();
  81.     for ( ;; )
  82.     {
  83.         if ( Token==T_IOR )
  84.         {
  85.             getoken();
  86.             ival = popint();
  87.             expr4();
  88.             pushint( popint() | ival );
  89.         }
  90.         else
  91.             return;
  92.     }
  93. }
  94.  
  95.  
  96. expr4()
  97. {
  98.     int ival;
  99.  
  100.     expr5();
  101.     for ( ;; )
  102.     {
  103.         if ( Token==T_AND )
  104.         {
  105.             getoken();
  106.             ival = popint();
  107.             expr5();
  108.             pushint( popint() & ival );
  109.         }
  110.         else
  111.             return;
  112.     }
  113. }
  114.  
  115. expr5()
  116. {
  117.     int ival;
  118.  
  119.     expr6();
  120.     for ( ;; )
  121.     {
  122.         if ( Token==T_XOR )
  123.         {
  124.             getoken();
  125.             ival = popint();
  126.             expr6();
  127.             pushint( popint() ^ ival );
  128.         }
  129.         else
  130.             return;
  131.     }
  132. }
  133.  
  134. expr6()
  135. {
  136.     int ival;
  137.  
  138.     expr7();
  139.     for ( ;; )
  140.     {
  141.         if ( Token==T_EQ )
  142.         {
  143.             getoken();
  144.             ival = popint();
  145.             expr7();
  146.             pushint( ival == popint() );
  147.         }
  148.         else if ( Token==T_NE )
  149.         {
  150.             getoken();
  151.             ival = popint();
  152.             expr7();
  153.             pushint( ival != popint() );
  154.         }
  155.         else
  156.             return;
  157.     }
  158. }
  159.  
  160. expr7()
  161. {
  162.     int ival;
  163.  
  164.     expr8();
  165.     for ( ;; )
  166.     {
  167.         if ( Token==T_LE )
  168.         {
  169.             getoken();
  170.             ival = popint();
  171.             expr8();
  172.             pushint( ival <= popint() );
  173.         }
  174.         else if ( Token==T_GE )
  175.         {
  176.             getoken();
  177.             ival = popint();
  178.             expr8();
  179.             pushint( ival >= popint() );
  180.         }
  181.         else if ( Token==T_LT )
  182.         {
  183.             getoken();
  184.             ival = popint();
  185.             expr8();
  186.             pushint( ival < popint() );
  187.         }
  188.         else if ( Token==T_GT )
  189.         {
  190.             getoken();
  191.             ival = popint();
  192.             expr8();
  193.             pushint( ival > popint() );
  194.         }
  195.         else
  196.             return;
  197.     }
  198. }
  199.  
  200. expr8()
  201. {
  202.     int ival;
  203.  
  204.     expr9();
  205.     for ( ;; )
  206.     {
  207.         if ( Token==T_SHL )
  208.         {
  209.             getoken();
  210.             ival = popint();
  211.             expr9();
  212.             pushint( ival << popint() );
  213.         }
  214.         else if ( Token==T_SHR )
  215.         {
  216.             getoken();
  217.             ival = popint();
  218.             expr9();
  219.             pushint( ival >> popint() );
  220.         }
  221.         else
  222.             return;
  223.     }
  224. }
  225.  
  226. expr9()
  227. {
  228.     int ival;
  229.  
  230.     expr10();
  231.     for ( ;; )
  232.     {
  233.         if ( Token==T_ADD )
  234.         {
  235.             getoken();
  236.             ival = popint();
  237.             expr10();
  238.             pushint( ival + popint() );
  239.         }
  240.         else if ( Token==T_SUB )
  241.         {
  242.             getoken();
  243.             ival = popint();
  244.             expr10();
  245.             pushint( ival - popint() );
  246.         }
  247.         else
  248.             return;
  249.     }
  250. }
  251.  
  252. expr10()
  253. {
  254.     int ival;
  255.  
  256.     primary();
  257.     for ( ;; )
  258.     {
  259.         if ( Token==T_MUL )
  260.         {
  261.             getoken();
  262.             ival = popint();
  263.             primary();
  264.             pushint( ival * popint() );
  265.         }
  266.         else if ( Token==T_DIV )
  267.         {
  268.             getoken();
  269.             ival = popint();
  270.             primary();
  271.             pushint( ival / popint() );
  272.         }
  273.         else if ( Token==T_MOD )
  274.         {
  275.             getoken();
  276.             ival = popint();
  277.             primary();
  278.             pushint( ival % popint() );
  279.         }
  280.         else
  281.             return;
  282.     }
  283. }
  284.  
  285. primary()
  286. {
  287.     int index;
  288.     DATUM data;
  289.     VARIABLE *pvar;
  290.  
  291.     switch ( Token )
  292.     {
  293.     case T_LPAREN:
  294.         /*
  295.          * it's a parenthesized expression
  296.          */
  297.         getoken();
  298.         expression();
  299.         if ( Token!=T_RPAREN )
  300.             error( "missing ')'", ACT_ERROR );
  301.         getoken();
  302.         break;
  303.     case T_LNOT:
  304.         getoken();
  305.         primary();
  306.         pushint( ! popint() );
  307.         break;
  308.     case T_NOT:
  309.         getoken();
  310.         primary();
  311.         pushint( ~ popint() );
  312.         break;
  313.     case T_ADD:
  314.         getoken();
  315.         primary();
  316.         break;
  317.     case T_SUB:
  318.         getoken();
  319.         primary();
  320.         pushint( - popint() );
  321.         break;
  322.     case T_INCR:
  323.     case T_DECR:
  324.         preincdec();
  325.         break;
  326.     case T_MUL:
  327.         getoken();
  328.         primary();
  329.         /*
  330.          * If item on stack is an LVALUE, do an extra level of
  331.          * indirection before changing it to an LVALUE.
  332.          */
  333.         if ( Stackptr->lvalue )
  334.             Stackptr->value.ptrptr = *Stackptr->value.ptrptr;
  335.         Stackptr->lvalue = 1;
  336.         --Stackptr->class;
  337.         break;
  338.     case T_AND:
  339.         getoken();
  340.         primary();
  341.         if ( Stackptr->lvalue )
  342.             Stackptr->lvalue = 0;
  343.         else
  344.             error( "'&' operator needs an lvalue", ACT_ERROR );
  345.         break;
  346.     case T_CONSTANT:
  347.         pushint( Value.ival );
  348.         getoken();
  349.         break;
  350.     case T_REGEXP:
  351.         /*
  352.          * It's a regular expression - parse it and compile it.
  353.          */
  354.         if ( Where == PATTERN )
  355.         {
  356.             /*
  357.              * We're processing a pattern right now - perform a
  358.              * match of the regular expression agains input line.
  359.              */
  360.             unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  361.             pushint( match( Linebuf, Value.dptr ) );
  362.         }
  363.         else
  364.             push( 1, ACTUAL, BYTE, &Value );
  365.         getoken();
  366.         break;
  367.     case T_NF:
  368.         pushint( Fieldcount );
  369.         getoken();
  370.         break;
  371.     case T_NR:
  372.         pushint( Recordcount );
  373.         getoken();
  374.         break;
  375.     case T_FS:
  376.         Fieldsep[1] = 0;
  377.         data.dptr = Fieldsep;
  378.         push( 0, LVALUE, BYTE, &data );
  379.         getoken();
  380.         break;
  381.     case T_RS:
  382.         Recordsep[1] = 0;
  383.         data.dptr = Recordsep;
  384.         push( 0, LVALUE, BYTE, &data );
  385.         getoken();
  386.         break;
  387.     case T_FILENAME:
  388.         data.dptr = Filename;
  389.         push( 1, ACTUAL, BYTE, &data );
  390.         getoken();
  391.         break;
  392.     case T_DOLLAR:
  393.         /*
  394.          * It's a reference to one (or all) of the words in Linebuf.
  395.          */
  396.         getoken();
  397.         primary();
  398.         if ( index = popint() )
  399.         {
  400.             if ( index > Fieldcount )
  401.                 index = Fieldcount;
  402.             else if ( index < 1 )
  403.                 index = 1;
  404.             data.dptr = Fields[ index-1 ];
  405.         }
  406.         else
  407.         {
  408.             /*
  409.              * Reconstitute the line buffer in case any of the
  410.              * fields have been changed.
  411.              */
  412.             unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  413.             data.dptr = Linebuf;
  414.         }
  415.         /*
  416.          * $<expr>'s are treated the same as string constants:
  417.          */
  418.         push( 1, ACTUAL, BYTE, &data );
  419.         break;
  420.     case T_STRING:
  421.         push( 1, ACTUAL, BYTE, &Value );
  422.         getoken();
  423.         break;
  424.     case T_FUNCTION:
  425.         /*
  426.          * Do a built-in function call
  427.          */
  428.         index = Value.ival;
  429.         getoken();
  430.         function( index );
  431.         break;
  432.     case T_VARIABLE:
  433.         pvar = Value.dptr;
  434.         getoken();
  435.         /*
  436.          * it's a plain variable. The way a variable is
  437.          * represented on the stack depends on its type:
  438.          *      lvalue class value.dptr
  439.          * vars:  1      0   address of var
  440.          * ptrs:  1      1   ptr to address of ptr
  441.          * array: 0      1   address of var
  442.          */
  443.         if ( pvar->vclass && !pvar->vlen )
  444.             /* it's a pointer */
  445.             data.dptr = &pvar->vptr;
  446.         else
  447.             /* an array or simple variable */
  448.             data.dptr = pvar->vptr;
  449.         /*
  450.          * If it's an array it can't be used as an LVALUE.
  451.          */
  452.         push( pvar->vclass, !pvar->vlen, pvar->vsize, &data );
  453.         break;
  454.     case T_EOF:
  455.         break;
  456.     default:
  457.         syntaxerror();
  458.     }
  459.     /*
  460.      * a "[" means it's an array reference
  461.      */
  462.     if ( Token==T_LBRACKET )
  463.     {
  464.         getoken();
  465.         if ( ! Stackptr->class )
  466.             error( "'[]' needs an array or pointer", ACT_ERROR );
  467.         /*
  468.          * compute the subscript
  469.          */
  470.         expression();
  471.         if ( Token!=T_RBRACKET )
  472.             error( "missing ']'", ACT_ERROR );
  473.         getoken();
  474.         index = popint();
  475.         /*
  476.          * compute the offset (subscript times two for int arrays)
  477.          * and then the effective address.
  478.          */
  479.         index *= Stackptr->size;
  480.         if ( Stackptr->lvalue )
  481.             /*
  482.              * It's a pointer - don't forget that the stack top
  483.              * item's value is the address of the pointer so we
  484.              * must do another level of indirection.
  485.              */
  486.             Stackptr->value.dptr = *Stackptr->value.ptrptr+index;
  487.         else
  488.             /*
  489.              * It's a plain array - the stack top item's value is
  490.              * the address of the first element in the array.
  491.              */
  492.             Stackptr->value.dptr += index;
  493.  
  494.         /*
  495.          * The stack top item now becomes an LVALUE, but we've
  496.          * reduced the indirection level.
  497.          */
  498.         Stackptr->lvalue = 1;
  499.         --Stackptr->class;
  500.     }
  501.  
  502.     if ( Token==T_INCR || Token==T_DECR )
  503.         postincdec();
  504. }
  505.  
  506. preincdec()
  507. {
  508.     /*
  509.      * Pre increment/decrement
  510.      */
  511.     int incr;
  512.  
  513.     incr = Token==T_INCR ? 1 : -1;
  514.     getoken();
  515.     primary();
  516.     if ( Stackptr->lvalue )
  517.     {
  518.         if ( Stackptr->class )
  519.             incr *= Stackptr->size;
  520.         *Stackptr->value.ptrptr += incr;
  521.     }
  522.     else
  523.         error( "pre '++' or '--' needs an lvalue", ACT_ERROR );
  524. }
  525.  
  526. postincdec()
  527. {
  528.     /*
  529.      * Post increment/decrement
  530.      */
  531.     char **pp;
  532.     int incr;
  533.  
  534.     incr = Token==T_INCR ? 1 : -1;
  535.     getoken();
  536.     if ( Stackptr->lvalue )
  537.     {
  538.         if ( Stackptr->class )
  539.         {
  540.             /*
  541.              * It's a pointer - save its old value then
  542.              * increment/decrement the pointer.  This makes the
  543.              * item on top of the stack look like an array, which
  544.              * means it can no longer be used as an LVALUE. This
  545.              * doesn't really hurt, since it doesn't make much
  546.              * sense to say:
  547.              *   char *cp;
  548.              *   cp++ = value;
  549.              */
  550.             pp = *Stackptr->value.ptrptr;
  551.             *Stackptr->value.ptrptr += incr * Stackptr->size;
  552.             Stackptr->value.ptrptr = pp;
  553.         }
  554.         else
  555.         {
  556.             /*
  557.              * It's a simple variable - save its old value then
  558.              * increment/decrement the variable.  This makes the
  559.              * item on top of the stack look like a constant,
  560.              * which means it can no longer be used as an LVALUE.
  561.              * Same reasoning as above.
  562.              */
  563.             if ( Stackptr->size == BYTE )
  564.                 pp = *Stackptr->value.dptr;
  565.             else
  566.                 pp = *Stackptr->value.ptrptr;
  567.             *Stackptr->value.ptrptr += incr;
  568.             Stackptr->value.ival = pp;
  569.         }
  570.         Stackptr->lvalue = 0;
  571.     }
  572.     else
  573.         error( "post '++' or '--' needs an lvalue", ACT_ERROR );
  574. }
  575.  
  576. statement()
  577. {
  578.     /*
  579.      * Evaluate a statement
  580.      */
  581.     char *repeat, *body;
  582.  
  583.     switch ( Token )
  584.     {
  585.     case T_EOF:
  586.         break;
  587.     case T_CHAR:
  588.     case T_INT:
  589.         declist();
  590.         break;
  591.     case T_LBRACE:
  592.         /*
  593.          * parse a compound statement
  594.          */
  595.         getoken();
  596.         while ( !Saw_break && Token!=T_RBRACE )
  597.             statement();
  598.  
  599.         if ( Token==T_RBRACE )
  600.             getoken();
  601.         break;
  602.     case T_IF:
  603.         /*
  604.          * parse an "if-else" statement
  605.          */
  606.         if ( getoken() != T_LPAREN )
  607.             syntaxerror();
  608.         getoken();
  609.         expression();
  610.         if ( Token!=T_RPAREN )
  611.             syntaxerror();
  612.         getoken();
  613.         if ( popint() )
  614.         {
  615.             statement();
  616.             if ( Token==T_ELSE )
  617.             {
  618.                 getoken();
  619.                 skipstatement();
  620.             }
  621.         }
  622.         else
  623.         {
  624.             skipstatement();
  625.             if ( Token==T_ELSE )
  626.             {
  627.                 getoken();
  628.                 statement();
  629.             }
  630.         }
  631.         break;
  632.     case T_WHILE:
  633.         /*
  634.          * parse a "while" statement
  635.          */
  636.         repeat = Actptr;
  637.         for ( ;; )
  638.         {
  639.             if ( getoken() != T_LPAREN )
  640.                 syntaxerror();
  641.  
  642.             getoken();
  643.             expression();
  644.             if ( Token!=T_RPAREN )
  645.                 syntaxerror();
  646.  
  647.             if ( popint() )
  648.             {
  649.                 body = Actptr;
  650.                 getoken();
  651.                 statement();
  652.                 if ( Saw_break )
  653.                 {
  654.                     Actptr = body;
  655.                     Saw_break = 0;
  656.                     break;
  657.                 }
  658.                 Actptr = repeat;
  659.             }
  660.             else
  661.                 break;
  662.         }
  663.         getoken();
  664.         skipstatement();
  665.         break;
  666.     case T_BREAK:
  667.         /*
  668.          * parse a "break" statement
  669.          */
  670.         getoken();
  671.         Saw_break = 1;
  672.         break;
  673.     case T_SEMICOLON:
  674.         break;
  675.     default:
  676.         expression();
  677.         popint();
  678.     }
  679.  
  680.     if ( Token==T_SEMICOLON )
  681.         getoken();
  682. }    
  683.  
  684. skipstatement()
  685. {
  686.     /*
  687.      * Skip a statement
  688.      */
  689.  
  690.     switch ( Token )
  691.     {
  692.     case T_LBRACE:
  693.         /*
  694.          * skip a compound statement
  695.          */
  696.         skip( T_LBRACE, T_RBRACE );
  697.         break;
  698.     case T_IF:
  699.         /*
  700.          * skip an "if-else" statement
  701.          */
  702.         getoken();    /* skip 'if' */
  703.         skip( T_LPAREN, T_RPAREN );
  704.         skipstatement();
  705.         if ( Token==T_ELSE )
  706.         {
  707.             getoken();    /* skip 'else' */
  708.             skipstatement();
  709.         }
  710.         break;
  711.     case T_WHILE:
  712.         /*
  713.          * skip a "while" statement
  714.          */
  715.         getoken();    /* skip 'while' */
  716.         skip( T_LPAREN, T_RPAREN );
  717.         skipstatement();
  718.         break;
  719.     default:
  720.         /*
  721.          * skip a one-liner
  722.          */
  723.         while (Token!=T_SEMICOLON && Token!=T_RBRACE && Token!=T_EOF)
  724.             getoken();
  725.         if ( Token==T_EOF )
  726.             error( "unexpected end", ACT_ERROR );
  727.         if ( Token==T_SEMICOLON )
  728.             getoken();
  729.     }
  730. }
  731.  
  732. skip( left, right )
  733. char left, right;
  734. {
  735.     /*
  736.      * Skip matched left and right delimiters and everything in between
  737.      */
  738.     int parity;
  739.     char *save, errmsg[ 80 ];
  740.  
  741.     parity = 1;
  742.     save = Actptr;
  743.     while ( getoken() != T_EOF )
  744.     {
  745.         if ( Token == left )
  746.         {
  747.             save = Actptr;
  748.             ++parity;
  749.         }
  750.         else if ( Token == right )
  751.             --parity;
  752.         if ( !parity )
  753.         {
  754.             getoken();
  755.             return;
  756.         }
  757.     }
  758.     Actptr = save;
  759.  
  760.     sprintf( errmsg, "mismatched '%c' and '%c'", left, right );
  761.     error( errmsg, ACT_ERROR );
  762. }
  763.  
  764. syntaxerror()
  765. {
  766.     error( "syntax error", ACT_ERROR );
  767. }
  768.